import 'dart:math';

import 'package:flutter/material.dart';
import 'package:homepad/logger/logger.dart';

class LightColorView extends StatefulWidget {
  final int hue;
  final int saturation;
  final bool enable;
  final ValueChanged<({int hue, int saturation})>? onChanged;

  LightColorView({
    super.key,
    required this.hue,
    required this.saturation,
    required this.enable,
    this.onChanged,
  }) {
    logger.info("hue: $hue saturation:$saturation");
  }

  @override
  State<StatefulWidget> createState() => _LightColorView();
}

class _LightColorView extends State<LightColorView> {
  static const height = 400.0;
  static const width = 400.0;
  static const radius = 20.0;
  static const diameter = 155.0 * 2;

  Color _color = Colors.white;
  Offset _offset = const Offset(width / 2, height / 2);
  double _dxy = 0;

  void _setOffset(Offset value, {bool update = false}) {
    if (!widget.enable) {
      return;
    }
    // 触摸点距离圆心的距离
    var px = value.dx - width / 2;
    var py = value.dy - height / 2;
    var r = sqrt(px * px + py * py);

    // 计算出实际的角度
    var angle = (180 * asin(py / r) / pi).toInt();
    if (px < 0 && py < 0) {
      angle = 180 - angle;
    } else if (px < 0) {
      angle = 180 - angle;
    } else if (px >= 0 && py < 0) {
      angle = 360 + angle;
    }
    angle = (angle + 90) % 360;

    // 超过圆的半径的点，取距离圆角边缘最近的点的颜色
    var x = value.dx;
    var y = value.dy;
    if (r > diameter / 2) {
      var scale = diameter / 2 / r;
      x = width / 2 + (value.dx - width / 2) * scale;
      y = height / 2 + (value.dy - height / 2) * scale;
      r = diameter / 2;
    }

    var hue = angle;
    var saturation = pow(r * 2 / diameter, 1.7);
    var lightness = 1.0;
    final hsvColor = HSVColor.fromAHSV(1.0, hue.toDouble(), saturation.toDouble(), lightness);

    var color = (hue: (hsvColor.hue + 0.5).toInt(), saturation: (hsvColor.saturation * 100 + 0.5).toInt());
    if (update) {
      widget.onChanged?.call(color);
    }
    _dxy = sqrt((_offset.dx - x) * (_offset.dx - x) + (_offset.dy - y) * (_offset.dy - y));
    if (_dxy.toInt() < 2) {
      return;
    }
    logger.info("radius:${r.toInt()} angle:${angle.toInt()} _dxy: ${_dxy.toInt()}");
    _updateColor(color.hue, color.saturation);
  }

  LightColorView? _lastWidget;
  void _updateColor(int hue, int saturation) {
    logger.info("update hue:$hue saturation:$saturation");
    final angle = (hue - 90) % 360;
    final radius = pow(saturation / 100, 1 / 1.7) * (diameter / 2);
    final x = (width / 2 + radius * cos(angle / 180.0 * pi)).toDouble();
    final y = (height / 2 + radius * sin(angle / 180.0 * pi)).toDouble();
    logger.info("x:$x y:$y");
    _color = HSVColor.fromAHSV(1.0, hue.toDouble(), saturation / 100, 1.0).toColor();
    setState(() {
      _offset = Offset(x, y);
      _lastWidget = widget;
    });
  }

  @override
  Widget build(BuildContext context) {
    if (_lastWidget == null || _lastWidget != widget) {
      _updateColor(widget.hue, widget.saturation);
    }
    return GestureDetector(
      onPanDown: (detail) => _setOffset(detail.localPosition),
      onPanStart: (detail) => _setOffset(detail.localPosition),
      onPanEnd: (detail) => _setOffset(detail.localPosition, update: true),
      onPanUpdate: (detail) => _setOffset(detail.localPosition),
      child: SizedBox(
          width: height,
          height: width,
          child: Stack(
            children: [
              const Image(
                image: AssetImage("assets/images/bg_light_color_hsb.png"),
              ),
              AnimatedContainer(
                duration: Duration(milliseconds: _dxy > 50 ? 500 : 50),
                margin: EdgeInsets.only(top: _offset.dy - radius, left: _offset.dx - radius),
                width: radius * 2,
                height: radius * 2,
                decoration: BoxDecoration(
                    color: _color,
                    borderRadius: const BorderRadius.all(Radius.circular(20)),
                    border: Border.all(width: 2, color: const Color.fromARGB(200, 255, 255, 255)),
                    boxShadow: [
                      BoxShadow(
                        color: Colors.grey.withOpacity(0.4),
                        spreadRadius: 1,
                        blurRadius: 2,
                        offset: const Offset(1, 1),
                      )
                    ]),
              )
            ],
          )),
    );
  }
}
